#if !defined(_AOBJECT_H_)
#define _AOBJECT_H_

#include <map>
#include <list>
#include <string>
#include <vector>
#include <stack>

#pragma warning(disable: 4996)

using namespace std;
typedef vector<std::string> strings;
typedef std::string CAString;

#include "cocos2d.h"
using namespace cocos2d;
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;

#define A2R(angle) ((angle) * 3.14159265f / 180.0f)
#define R2A(rota) ((rota) / 3.14159265f * 180.0f)

typedef unsigned int uint32;
typedef unsigned short uint18;
typedef unsigned char uint8;

#if !defined(null)
#	define null NULL
#endif

typedef CCObject CAObject;

#include "AUtils.h"

#define RES(a) CCFileUtils::fullPathFromRelativePath(a)

#define MAP_FOREACH(__val_type__, __val__, __map__, __func__)	\
	{	\
		CCDictElement* pElement##for##__val__ = NULL; \
		CCDictionary* __pmap__##for##__val__ = __map__; \
		CCDICT_FOREACH(__pmap__##for##__val__, pElement##for##__val__) \
		{ \
			__val_type__ __val__ = (__val_type__)(pElement##for##__val__)->getObject(); \
			__func__; \
		} \
	}

template<class _T = CCObject>
class CAStringMap : public CCDictionary //CCMutableDictionary<CAString, _T*>
{
public:
	_T* objectForKey(const CAString& key)
	{
		return (_T*)CCDictionary::objectForKey(key);
	};
};

template<class _T = CCObject>
class CAObjectList : public CAObject
{
protected:
	std::list<_T*> _list;
public:
	CAObjectList() {}
	virtual ~CAObjectList() 
	{
		while (null != removeBegin())
		{
			;
		}
	};

	size_t count() const { return _list.size(); }

	void addObject(_T* pobj)
	{
		_list.push_back(pobj);
		pobj->retain();
	}
	void removeObject(_T* pobj)
	{
		pobj->release();
		_list.remove(pobj);
	}

	_T* peekBegin()
	{
		if (_list.size() <= 0)
			return null;

		return *_list.begin();
	}
	_T* removeBegin()
	{
		if (_list.size() <= 0)
			return null;

		_T* pobj = *_list.begin();
		_list.pop_front();
		pobj->release();
		return pobj;
	}
};

#define CCARRAY_FIND(objs, obj, condi) \
{\
	CCARRAY_FOREACH(objs, obj)\
	{\
		if (condi)\
		{\
			break;\
		}\
	}\
}

typedef CCAction CAAction;

class CATimeProvider
{
protected:
	ccTime _timeTotal;
	ccTime _timeNow;
	ccTime _timeDelta;
	float _timeScale;

	inline void _updateTime(ccTime dt)
	{
		dt *= _timeScale;
		_timeTotal += dt;
		_timeNow += dt;
		_timeDelta = dt;
	}
public:
	inline float getTimeTotal() const { return 	_timeTotal; };
	inline float getTimeNow() const { return _timeNow; }
	inline float getTimeDelta() const { return _timeDelta; }
	inline void setTimeOffset(float o) { _timeTotal += o; _timeNow += o; }
	inline void setTimeTotal(float t) { _timeTotal = t; };
	inline void setTimeNow(float t) { _timeNow = t; }
	inline void setTimeDelta(float t) { _timeDelta = t; }
	inline void setTimeScale(float s) {_timeScale = s; }

	inline void resetTimer()
	{
		_timeNow = 0;
		_timeDelta = 0;
		_timeTotal = 0;
	}
};

#define CA_IMPLEMENTS ,

#include "ADebug.h"

#define _Abs(a)	(((a) > 0) ? (a) : (-(a)))
#define _Max(a, b) ((a) > (b) ? (a) : (b))
#define _Min(a, b) ((a) < (b) ? (a) : (b))

#define SIZE_OF_ARRAY(a)		(sizeof(a) / sizeof(a[0]))
	
#define RECORD_OFFSET(type, field)			((LONG)(int*)&(((type *)0)->field))
#define RECORD_SIZE(type, field)			sizeof(((type *)0)->field)
#define RECORDS_SIZE(type, field1, field2)	(RECORD_OFFSET(type, field2) - RECORD_OFFSET(type, field1) + RECORD_SIZE(type, field2))
	
#define ALIGN_IN_NBYTES(a, n)	((((a) + ((n) - 1)) / (n)) * (n))
#define ALIGN_IN_N2BYTES(a, n2)	(((a) + ((n2) - 1)) & (~((n2) - 1)))
#define ALIGN_IN_4BYTES(a)		(((a) + 3) & (~3))

#define MAGIC2(a, b)			((WORD)(((b) << 8) | (a)))
#define MAGIC4(a, b, c, d)		((DWORD)((MAGIC2(c, d) << 16) | MAGIC2(a, b)))

#define INTABS(a)				(((a) > 0) ? (a) : (-(a)))
#define BOUND(a, mm, bb)		min(max(a, mm), bb)
#define CLAMP(v, mi, ma)		min(max(v, mi), ma)
//if (v < mi) { return mi; } else if (value > ma) { return ma;} else { return v; }

#define CLAMP_RANGE(a, b, e)	((b) + ((a) % max(1, ((e) - (b)))))

#define PERCENT(v, v0, v1) ((v) - (v0) + 0.0000001f) / ((v1) - (v0) + 0.0000001f)

#if defined(_DEBUG) && (defined(WIN32) || defined(_CONSOLE))
	#define _USE_MEM_GUARDER_
#endif

void *gMemAlloc (unsigned int size);
void *gMemAllocAligned (int align, unsigned int size, void** ppvRealAddr);
void gMemFree (void *pv);

#if defined(_USE_MEM_GUARDER_)
	#define MAX_LEN_OF_FUNCTION_NAME	512
	#define MAX_FUNCTION_DEPTH			32
	//exception will use this class 2

	class FunctionGuard
	{
	public:
		static char m_szCallStack[MAX_FUNCTION_DEPTH][MAX_LEN_OF_FUNCTION_NAME];
		static int m_nDepth;
	public:
		static int FunctionEnter (const char *szFunc, const char* pszfile, int line);
		static int FunctionLeave ();
		static int GetCallStackStringLen (int dep = -1);
		static int GetCallStack (char *szcs, int len, int dep = -1);
	};

	class FunctionGuardDriver
	{
	public:
		FunctionGuardDriver (const char *name, const char* pszfile, int line)
		{ FunctionGuard::FunctionEnter (name, pszfile, line); }
		~FunctionGuardDriver ()
		{ FunctionGuard::FunctionLeave (); }
	};
	
	#define GUARD_FIELD(field) FunctionGuardDriver __care_func_guard__driver_##field(__FUNCTION__ "@" #field, __FILE__, __LINE__)
	#define GUARD_FUNCTION() FunctionGuardDriver __care_func_guard_driver__(__FUNCTION__, __FILE__, __LINE__)

	void gDumpMemoryAllocInfo (BOOL bDetails);
	void gCheckMemoryBlocks();
	unsigned int gGetMemSizeAlloced();
	unsigned int gGetMemMaxSizeAlloced();
#else //defined(_USE_MEM_GUARDER_)
	#define GUARD_FUNCTION() 
	#define GUARD_FIELD(a) 

	#define gDumpMemoryAllocInfo(bDetals)
	#define gCheckMemoryBlocks()
	#define gGetMemSizeAlloced()	(0)
	#define gGetMemMaxSizeAlloced() (0)
		
#endif //defined(_USE_MEM_GUARDER_)


#if !defined(_NO_ULE_NEW_OPERATORS_NEW_)
#if defined(_USE_MEM_GUARDER_)
#if !defined(_OPERATOR_PREFIX_)
	#define _OPERATOR_PREFIX_ __cdecl
#endif
	inline void*_OPERATOR_PREFIX_ operator	new (size_t size)					{ return gMemAlloc (size); }
	inline void _OPERATOR_PREFIX_ operator	delete (void *p)					{ gMemFree (p);			}
	inline void*_OPERATOR_PREFIX_ operator	new[] (size_t size)					{ return gMemAlloc (size);	}
	inline void _OPERATOR_PREFIX_ operator	delete[] (void *p)					{ gMemFree (p);			}
	inline void*_OPERATOR_PREFIX_ operator	new (size_t size, const char*, int)	{ return operator new (size);	}
	inline void*_OPERATOR_PREFIX_ operator	new[] (size_t size,const char*, int){ return operator new (size);	}
	inline void _OPERATOR_PREFIX_ operator	delete (void *p, const char*, int)	{ operator delete (p);			}
	inline void _OPERATOR_PREFIX_ operator	delete[] (void *p, const char*, int){ operator delete (p);			}
#else //_USE_MEM_GUARDER_
#endif //_USE_MEM_GUARDER_
#endif //_NO_ULE_NEW_OPERATORS_NEW_


#include "AFixArray.h"
#include "AAnimate.h"

typedef enum enumAnimationMode
{
	AM_LOOP = 0,	//abcabcabc
	AM_CLAMP,		//abc0
	AM_REVERSE,		//abcbabcba
	AM_EXTENDS,		//abccccccc
}
EAnimationMode;

EAnimationMode String2AnimateMode(const CAString& mode);

#endif //_AOBJECT_H_
